home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / PTR-TCL v2.1 / Support / New TCL Source / x.h < prev   
Encoding:
C/C++ Source or Header  |  1994-02-17  |  7.6 KB  |  256 lines  |  [TEXT/MMCC]

  1. #ifndef __X__
  2. # define __X__
  3.  
  4. /*
  5.  * x.h ©1993 Jon Wätte (h+@nada.kth.se) All Rights Reserved.
  6.  * Please read the paragraph marked $$$ below before using this
  7.  * source file.
  8.  *
  9.  * v1.0 930826 - Initial Release
  10.  * v1.1 940115 - "Replacing" the Think Class Library scheme
  11.  * v1.1.1 940217 - Adding TRY_MULTIPLE and fixing RETRY
  12.  */
  13.  
  14. /*
  15.  * This try/fail system was inspired by how the Think Class Library
  16.  * exception mechanism works. No code was taken from the TCL, and I have
  17.  * not even studied the source of the TCL exception mechanism.
  18.  *
  19.  * You use it by encapsulating code that might fail in
  20.  *
  21.  * TRY {
  22.  *    <code>
  23.  * } CATCH {
  24.  *    <error handler>
  25.  * } DONE ;
  26.  *
  27.  * If your error handler does not want to keep doing exceptions
  28.  * that this exception might be encapsulated in, it should look
  29.  * something like this:
  30.  * ...
  31.  * } CATCH {
  32.  *    <error handler>
  33.  *    NO_PROPAGATE ;
  34.  * } DONE ;
  35.  *
  36.  * There are cases where you want to do something like restore the state
  37.  * of a handle both when catching failures and when done with the critical
  38.  * section normally - in that case, you can use CLEANUP instead of CATCH:
  39.  *
  40.  *    void
  41.  *    Function ( Handle h ) {
  42.  *
  43.  *    char state = HGetState ( h ) ;
  44.  *
  45.  *        HLock ( h ) ;
  46.  *        TRY {
  47.  *            DoSomethingTo ( * h ) ;
  48.  *        } CLEANUP {
  49.  *            HSetState ( h , state ) ;
  50.  *        } DONE ;
  51.  *
  52.  * The code between CLEANUP and DONE will be executed for both exception
  53.  * cases and normal execution - HOWEVER, an exception will jump to the next
  54.  * upward exception handler at DONE while the normal code will continue.
  55.  * You can modify this behaviour with NO_PROPAGATE ;
  56.  *
  57.  * To trigger an exception, you call FailErr(e) with a non-0 e, or you call
  58.  * FailNil(p) with a NULL p (in which case a -108 error is generated) If you
  59.  * want to know what error you are handling in an error handler, it is stored
  60.  * in the __err variable that is in scope in the whole TRY { } CATCH { } DONE
  61.  * construct. NO_PROPAGATE ; sets this variable to 0.
  62.  *
  63.  * If you #define FAILINFO below, you will additionally have a C string with
  64.  * the name of the offending file in __err_file and an int with the offending
  65.  * line number in __err_line. This option will generate more string data in
  66.  * your program (one string per call of FailErr or FailNil) so you may want to
  67.  * turn it off before release (and write your failure handling routine conditional
  68.  * on FAILINFO)
  69.  *
  70.  * If the outermost failure layer reaches DONE, bad things happen. This is because
  71.  * you are supposed to provide a failure handler there and call NO_PROPAGATE. My
  72.  * application typically looks like:
  73.  *
  74.  *    void
  75.  *    main ( void ) {
  76.  *
  77.  *        InitToolbox ( ) ;
  78.  *        TRY {
  79.  *            InitApp ( ) ;
  80.  *            while ( ! quit ) {
  81.  *                TRY {
  82.  *                    ProcessEvent ( ) ;
  83.  *                } CATCH {
  84.  *                    ReportError ( __err ) ;
  85.  *                    NO_PROPAGATE ;
  86.  *                } DONE ;
  87.  *            }
  88.  *        } CLEANUP {
  89.  *            QuitApp ( ) ;
  90.  *            if ( __err ) {
  91.  *                ReportStartQuitErr ( __err ) ;
  92.  *                ExitToShell ( ) ;
  93.  *            }
  94.  *        } DONE ;
  95.  *    }
  96.  *
  97.  * ReportError might look something like: (NOTE: The use of ParamText is NOT
  98.  * WorldScript compatible!)
  99.  *
  100.  *    static void
  101.  *    ReportError ( short errCode , Boolean toQuit ) {
  102.  *
  103.  *    StringHandle h = GetString ( errCode ) ;
  104.  *    Str15 code ;
  105.  *    StringHandle num ;
  106.  *    Str31 fileStr ;
  107.  *    Str15 lineStr ;
  108.  *
  109.  *        DisposeHandle ( err_safeguard ) ; /* Handle allocated in InitApp to give us some room * /
  110.  *        if ( ! h ) {
  111.  *            h = GetString ( 129 ) ; /* What do we do if this fails !? * /
  112.  *        }
  113.  *        HLock ( ( Handle ) h ) ;
  114.  *        NumToString ( errCode , code ) ;
  115.  *        num = GetString ( 130 ) ;
  116.  *        if ( num ) {
  117.  *            PtrAndHand ( ( Ptr ) & code [ 1 ] , ( Handle ) num , code [ 0 ] ) ;
  118.  *            * * num += code [ 0 ] ;
  119.  *            HLock ( ( Handle ) num ) ;
  120.  *        }
  121.  *
  122.  *    #ifdef FAILINFO
  123.  *        NumToString ( __err_line , lineStr ) ;
  124.  *        CopyC2P ( __err_file , fileStr ) ; /* Make fileStr the Pascal version of __err_file * /
  125.  *    #else
  126.  *        lineStr [ 0 ] = fileStr [ 0 ] = 0 ;
  127.  *    #endif
  128.  *
  129.  *        ParamText ( h ? * h : NULL , num ? * num : NULL , fileStr , lineStr ) ;
  130.  *        if ( num ) {
  131.  *            ReleaseResource ( ( Handle ) num ) ;
  132.  *        }
  133.  *        if ( h ) {
  134.  *            ReleaseResource ( ( Handle ) h ) ;
  135.  *        }
  136.  *        if ( ! InFront ( ) ) {
  137.  *            Notify ( ) ; /* Post notification since we're in the background * /
  138.  *        }
  139.  *        Alert ( 128 , NULL ) ; /* Could use a filterProc here * /
  140.  *        HiliteMenu ( 0L ) ; /* For failures during menu selections * /
  141.  *        ParamText ( NULL , NULL , NULL , NULL ) ;
  142.  *        err_safeguard = NewHandle ( 1024 ) ;
  143.  *    }
  144.  *
  145.  * New for 1.1: (940206)
  146.  * If you want to use more than one try/catch handler withing a function scope,
  147.  * you should use TRY_MULTIPLE, which removes the capability of doing a RETRY
  148.  * but does not use a (constant) label name in a macro.
  149.  *
  150.  * This exception system is written COMPLETELY in ANSI C. It is also FreeWare
  151.  * in the sense that you may use it, modified or not, in any product you
  152.  * make, as long as you send the author (me, Jon Wätte, h+@nada.kth.se) a
  153.  * copy of any product you make using this exception system. You may *NOT*
  154.  * distribute copies of these files (x.c and x.h) that are changed, renamed
  155.  * or in any other way modified from the originals as released by me.
  156.  *
  157.  * $$$ Also, please note, that I neither CAN nor WILL take any responsibility
  158.  * for your use of this source code; you use it solely AT YOUR OWN RISK, and
  159.  * if your use of this code or any derivative thereof results in damages to
  160.  * you or a third party, you are solely responsible for covering all such
  161.  * damages and costs related thereto. This code is provided by the author free
  162.  * of charge. IF THE ABOVE LIMITATION OF JON WÄTTE'S RESPONSIBILITY IS NOT LEGAL
  163.  * WHERE YOU USE OR PUBLISH THIS CODE OR THE RESULTS THEREOF, you are STRICTLY
  164.  * FORBIDDEN to use this code, ON THE PENALTY OF USD $1,000,000,000 (one
  165.  * billion US dollars) or SEK 10,000,000,000 (ten billion Swedish Crowns)
  166.  * whichever is greater, in damages for breach of contract and copyright
  167.  * infringement. I MEAN IT.
  168.  *
  169.  * If you want to fix bugs, CONTACT ME and I will incorporate the bug fix in
  170.  * the next general release.
  171.  *
  172.  */
  173.  
  174. #pragma once
  175. #ifndef x_h
  176. # define x_h
  177.  
  178. /* Define FAILINFO to get information about where something went wrong
  179.  * in failure alerts.
  180.  * Comment it out to save global/string data space
  181.  */
  182. # define FAILINFO
  183.  
  184. # include <setjmp.h>
  185.  
  186. # if defined(__cplusplus)
  187. extern "C" {
  188. # endif
  189.  
  190. # ifdef FAILINFO
  191. void __FailNil ( void * , char * , int ) ;
  192. void __FailErr ( OSErr , char * , int ) ;
  193. void __Failure ( short , long , char * , int ) ;
  194. #  define FailNil(x) __FailNil(x,__FILE__,__LINE__)
  195. #  define FailErr(x) __FailErr(x,__FILE__,__LINE__)
  196. #  define Failure(e,c) __Failure(e,c,__FILE__,__LINE__)
  197. extern char * __err_file ;
  198. extern int __err_line ;
  199. # else
  200. void FailNil ( void * ) ;
  201. void FailErr ( OSErr ) ;
  202. void Failure ( short err , long message ) ;
  203. # endif
  204.  
  205. extern short gLastError ;
  206. extern long gLastMessage ;
  207. extern jmp_buf * __cur_buf ;
  208.  
  209. # if defined(__cplusplus)
  210. }
  211. # endif
  212.  
  213.  
  214. # define TRY \
  215.     { short __err ; jmp_buf __jbuf ; jmp_buf * __last_top = __cur_buf ; \
  216.         if ( ! ( __err = setjmp ( __jbuf ) ) ) { __retry : __cur_buf = & __jbuf ; {
  217.  
  218. # define TRY_MULTIPLE \
  219.     { short __err ; jmp_buf __jbuf ; jmp_buf * __last_top = __cur_buf ; \
  220.         if ( ! ( __err = setjmp ( __jbuf ) ) ) { __cur_buf = & __jbuf ; {
  221.  
  222. # define CATCH \
  223.         } } else { __cur_buf = __last_top ; {
  224.  
  225. # define CLEANUP \
  226.         } __err = 0 ; goto __cleanup ; } else { __cur_buf = __last_top ; __cleanup : {
  227.  
  228. # define DONE \
  229.             } if ( __err ) { \
  230.                 if ( ! __cur_buf ) { DebugStr ( ( const unsigned char * ) "\pException Underflow" ) ; } ; \
  231.                 longjmp ( * __cur_buf , __err ) ;\
  232.             } \
  233.         } \
  234.         __cur_buf = __last_top ; \
  235.     }
  236.  
  237. # define NO_PROPAGATE \
  238.     __err = 0 ;
  239.  
  240. # define RETRY \
  241.     __err = 0 ; \
  242.     goto __retry ;
  243.  
  244. #ifndef FALSE
  245. # define FALSE false
  246. #endif
  247. #ifndef TRUE
  248. # define TRUE true
  249. #endif
  250.  
  251.  
  252. #endif /* x_h */
  253.  
  254.  
  255. #endif
  256.